package top.lidee.common.config;


import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.*;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import top.lidee.common.bean.WxPayV3Bean;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;

/**
 * @author 张一恒
 * @version 1.0
 * @description: 微信 创建加载商户私钥、加载平台证书、初始化httpClient的通用方法
 * @date 2024/9/30 15:26
 */
@Configuration
@Slf4j
public class WechatpayHttpClientConfig {


    @Autowired
    private WxPayV3Bean wxPayV3Bean;

    /**
     * 获取商户的私钥文件
     * @param filename
     * @return
     */
    private static PrivateKey getPrivateKey(String filename){

        try {
            return PemUtil.loadPrivateKey(new FileInputStream(filename));
        } catch (FileNotFoundException e) {
            throw new RuntimeException("私钥文件不存在", e);
        }
    }

    public static void main(String[] args) {
        System.out.println(getPrivateKey("C:\\yufubaosoft\\keys\\wechat\\apiclient_key.pem"));
    }


    /**
     * 获取签名验证器
     * @return
     */
    @Bean
    public Verifier getVerifier() throws Exception {
        log.info("获取签名验证器");
        //获取商户私钥
        PrivateKey privateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(wxPayV3Bean.getPrivateKey().getBytes(StandardCharsets.UTF_8)));
        // 私钥签名对象
        PrivateKeySigner keySigner = new PrivateKeySigner(wxPayV3Bean.getMchSerialNo(), privateKey);
        // 身份认证对象
        WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(wxPayV3Bean.getMchId(), keySigner);

        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        // 向证书管理器增加需要自动更新平台证书的商户信息
        certificatesManager.putMerchant(wxPayV3Bean.getMchId(), wechatPay2Credentials,
                wxPayV3Bean.getApiV3Key().getBytes(StandardCharsets.UTF_8));
        // ... 若有多个商户号，可继续调用putMerchant添加商户信息
        Verifier verifier = certificatesManager.getVerifier(wxPayV3Bean.getMchId());

        return verifier;
    }

    /**
     * 获取http请求对象
     * @param verifier
     * @return
     */
    @Bean
    public CloseableHttpClient getWxPayClient(Verifier verifier){

        log.info("获取httpclient");

        //获取商户私钥
        PrivateKey privateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(wxPayV3Bean.getPrivateKey().getBytes(StandardCharsets.UTF_8)));
        // 从证书管理器中获取verifier
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(wxPayV3Bean.getMchId(), wxPayV3Bean.getMchSerialNo(), privateKey)
                .withValidator(new WechatPay2Validator(verifier));
        // ... 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient

        // 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签，并进行证书自动更新
        CloseableHttpClient httpClient = builder.build();
        return httpClient;
    }

    /**
     * 获取HttpClient，无需进行应答签名验证，跳过验签的流程
     */
    @Bean(name = "wxPayNoSignClient")
    public CloseableHttpClient getWxPayNoSignClient(){

//        获取商户私钥
        PrivateKey privateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(wxPayV3Bean.getPrivateKey().getBytes(StandardCharsets.UTF_8)));

        //用于构造HttpClient
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                //设置商户信息
                .withMerchant(wxPayV3Bean.getMchId(), wxPayV3Bean.getMchSerialNo(), privateKey)
                //无需进行签名验证、通过withValidator((response) -> true)实现
                .withValidator((response) -> true);

        // 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签，并进行证书自动更新
        CloseableHttpClient httpClient = builder.build();

        log.info("== getWxPayNoSignClient END ==");
//        CloseableHttpClient httpClient = new DefaultHttpClient();
        return httpClient;
    }

}
